package com.bestcem.xm.ticket.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.ticket.constant.Constants;
import com.bestcem.xm.ticket.controller.convert.TicketConfigVOConvert;
import com.bestcem.xm.ticket.controller.param.ticket.config.CreateConfigParam;
import com.bestcem.xm.ticket.controller.param.ticket.config.TicketRuleParam;
import com.bestcem.xm.ticket.controller.param.ticket.config.TicketTemplateParam;
import com.bestcem.xm.ticket.controller.param.ticket.config.UpdateConfigParam;
import com.bestcem.xm.ticket.controller.param.ticket.config.createParam.ConditionParam;
import com.bestcem.xm.ticket.controller.param.ticket.config.createParam.TemplateDetailFieldParam;
import com.bestcem.xm.ticket.controller.vo.ticket.config.TemplateDetailFieldVO;
import com.bestcem.xm.ticket.controller.vo.ticket.config.TicketConfigInfoVO;
import com.bestcem.xm.ticket.dao.TicketConfigDao;
import com.bestcem.xm.ticket.dao.dto.TicketConfigInfo;
import com.bestcem.xm.ticket.entity.mongo.Ticket;
import com.bestcem.xm.ticket.entity.mongo.TicketConfig;
import com.bestcem.xm.ticket.entity.mongo.TicketRule;
import com.bestcem.xm.ticket.enums.TicketConfigStateEnum;
import com.bestcem.xm.ticket.grpc.client.TicketBaseQdesGrpcService;
import com.bestcem.xm.ticket.grpc.client.TicketBaseSurveyGrpcService;
import com.bestcem.xm.ticket.grpc.client.TicketBaseUserGrpcService;
import com.bestcem.xm.ticket.grpc.client.dto.qdes.QdesDTO;
import com.bestcem.xm.ticket.grpc.client.dto.survey.ColumnDTO;
import com.bestcem.xm.ticket.grpc.client.dto.user.UserDTO;
import com.bestcem.xm.ticket.service.*;
import com.bestcem.xm.ticket.service.convert.TicketRuleMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

import static com.bestcem.xm.ticket.constant.CommonConstant.CONFIG_SIZE_LIMIT;

/**
 * @author XiaoYunSong <ys.xiao@idiaoyan.com>
 * @version v1.0
 * @date 2021/8/18 11:07
 */
@Service
@Slf4j
public class TicketConfigServiceImpl implements TicketConfigService {
    @Resource
    private TicketConfigDao ticketConfigDao;

    @Resource
    private TicketService ticketService;

    @Resource
    private TicketRuleMapper ticketRuleMapper;

    @Resource
    private TicketRuleService ticketRuleService;

    @Resource
    private TicketNotifyConfigService ticketNotifyConfigService;

    @Resource
    private TicketFlowService ticketFlowService;

    @Resource
    private TicketBaseQdesGrpcService ticketBaseQdesGrpcService;
    @Resource
    private TicketBaseSurveyGrpcService ticketBaseSurveyGrpcService;
    @Resource
    private TicketBaseUserGrpcService ticketBaseUserGrpcService;

    /**
     * 更新工单规则的 标题
     *
     * @param id    工单规则id
     * @param title 新标题
     * @return 根据 result 的 success 判断成功与否
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/8/18 14:07
     */
    @Override
    public ServiceResult<Object> updateTicketConfigTitle(String id, String title) {
        TicketConfig entity = ticketConfigDao.findById(id);
        if (Objects.isNull(entity)) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.NOT_FOUND, "工单规则不存在");
        }
        if (ObjectUtils.isEmpty(title)) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "规则标题不能为空");
        }
        if (!title.equals(entity.getTitle())) {
            TicketConfig existedEntity = ticketConfigDao.findBySurveyIdAndTitle(entity.getSurveyId(), title);
            if (Objects.nonNull(existedEntity)) {
                return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_FORMAT, "规则标题重复");
            }
        }
        boolean successFlg = ticketConfigDao.updateTitle(id, title);
        if (!successFlg) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.WRITE_FAIL, "规则标题更新失败");
        }
        return ServiceResult.success();
    }

    /**
     * 更新工单规则的 状态
     *
     * @param id    工单规则id
     * @param state 新状态
     * @return 根据 result 的 success 判断成功与否
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/8/18 14:38
     */
    @Override
    public ServiceResult<Object> updateTicketConfigState(String id, TicketConfigStateEnum state) {
        TicketConfig entity = ticketConfigDao.findById(id);
        if (Objects.isNull(entity)) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.NOT_FOUND, "工单规则不存在");
        }
        if (ObjectUtils.isEmpty(state)) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "规则状态不能为空");
        }
        if (!(state.getIndex().equals(entity.getState()))) {
            boolean successFlg = ticketConfigDao.updateState(id, state);
            if (!successFlg) {
                return ServiceResult.failWithCode(ResourceErrorCodeEnum.WRITE_FAIL, "规则状态更新失败");
            }
        }
        return ServiceResult.success();
    }

    @Override
    public ServiceResult<String> insertTicketConfig(CreateConfigParam param) {
        if (!cn.hutool.core.lang.ObjectId.isValid(param.getSurveyId())) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_FORMAT, "Ticket qdes.Project[id=%s] not found");
        }

        List<String> configTitles = ticketConfigDao.listEnabledBySurveyId(param.getSurveyId());

        if (CollUtil.isNotEmpty(configTitles)) {
            int count = configTitles.size();
            // 校验行动规则数量
            if (count >= CONFIG_SIZE_LIMIT) {
                return ServiceResult.failWithCode(ResourceErrorCodeEnum.TOO_MUCH, "行动规则最多创建50个");
            }
            // 检查规则名称是否重复,同一个问卷中的规则名称唯一
            if (configTitles.contains(param.getTitle())) {
                return ServiceResult.failWithCode(ResourceErrorCodeEnum.FOUND, "规则标题重复");
            }
        }

        // 跟进处理必填校验
        boolean needDeal = Objects.nonNull(param.getNeedDeal()) && param.getNeedDeal();
        if (needDeal && CollUtil.isEmpty(param.getFollowConfig())) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "跟进处理信息不能为空");
        }

        // 通知内容必填校验,详情模板可以为空，处理模板不能为空
//        if (CollUtil.isEmpty(param.getTicketTemplate())) {
//            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "处理记录模板不能为空");
//        }

        /**
         * 在创建问卷预警工单规则的时候, 初始化工单配置.
         *     1. 初始化工单基础配置
         *     2. 初始化工单模板配置
         *     3. 初始化工单通知配置
         */
        // 请求qdes获取问卷id,get_project(survey_id)
        QdesDTO qdesProject = ticketBaseQdesGrpcService.getQdesProject(param.getSurveyId());
        // 如果获取问卷为空
        if (Objects.isNull(qdesProject)) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_FORMAT, "Ticket qdes.Project[id=%s] not found");
        }

        // 初始化工单配置
        TicketConfig newEntity = initTicketBaseConfig(param);

        // 初始化工单规则
        String ticketConfigId = newEntity.getId();
        // 初始化工单触发规则
        ServiceResult<String> ruleId = ticketRuleService.createTicketRule(ticketConfigId, param);
        if (!ruleId.isSuccess()) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, ruleId.getMsg());
        }
        newEntity.setTicketRuleId(ruleId.getData());

        // 初始化工单跟进人信息
        ServiceResult<List<String>> ticketFlowIds = ticketFlowService.createTicketFollow(ticketConfigId, param);
        if (!ticketFlowIds.isSuccess()) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, ruleId.getMsg());
        }
        newEntity.setTicketFlowIds(ticketFlowIds.getData());

        // 初始化工单处理模板
        // 保存处理模板
        if (CollUtil.isNotEmpty(param.getTicketTemplate())) {
            TicketTemplateParam ticketTemplateParam = param.getTicketTemplate().get(0);
            if (Objects.nonNull(ticketTemplateParam)) {
                if (cn.hutool.core.lang.ObjectId.isValid(ticketTemplateParam.getId())) {
                    newEntity.setTicketTemplateId(ticketTemplateParam.getId());
                }
            }
        }

        // 初始化工单通知配置
        List<String> notifyConfigIds = ticketNotifyConfigService.initTicketNotifyConfig(ticketConfigId, param);
        newEntity.setTicketNotifyConfigIds(notifyConfigIds);

        // 初始化工单状态变更规则
        newEntity.setStatusRuleList(ticketRuleService.initTicketStatusChangeRule(ticketConfigId, param));
        List<Ticket.TemplateDetailField> templateDetailFields = new ArrayList<>();
        if (!CollectionUtils.isEmpty(param.getTemplateDetailFields())) {
            for (TemplateDetailFieldParam templateDetailField : param.getTemplateDetailFields()) {
                templateDetailFields.add(TemplateDetailFieldParam.paramToEntity(templateDetailField));
            }
        }

        // 设置工单详情信息
        newEntity.setTemplateDetailFields(templateDetailFields);
        newEntity.setNeedDeal(needDeal);
        newEntity.setNeedRecord(param.getNeedRecord());
        newEntity.setRemindAdmin(param.getRemindAdmin());
        ticketConfigDao.updateTicketConfig(newEntity.getId(), newEntity);
        return ServiceResult.success(newEntity.getId());
    }

    @Override
    public ServiceResult<String> updateTicketConfigV2(String id, UpdateConfigParam param) {
        log.error("[Ticket] updateTicketConfig2={}", param);
        TicketConfig entity = ticketConfigDao.findById(id);
        if (Objects.isNull(entity)) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.NOT_FOUND, "TicketConfig[id={" + id + "}] not found");
        }
        // 检查规则名称是否重复,同一个问卷中的规则名称唯一
        if (!entity.getTitle().equals(param.getTitle())) {
            long l = ticketConfigDao.countEnabledBySurveyId(param.getSurveyId(), param.getTitle());
            if (l > 0L) {
                return ServiceResult.failWithCode(ResourceErrorCodeEnum.FOUND, "规则标题重复");
            }
        }

        // todo: 触发条件必填校验 参数中应该是condition

        // 工单 跟进处理必填校验
        boolean needDeal = Objects.nonNull(param.getNeedDeal()) && param.getNeedDeal();
        if (needDeal && CollUtil.isEmpty(param.getFollowConfig())) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "跟进处理信息不能为空");
        }

        // 工单 处理模板不能为空
        if (needDeal && ObjectUtils.isEmpty(param.getTicketTemplateId())) {
            return ServiceResult.failWithCode(ReqErrorCodeEnum.PARAM_LOST, "处理记录模板不能为空");
        }

        // 1、更新 工单生成规则
        this.updateTicketRule(entity, param);

        // 2、更新 工单流程
        ticketFlowService.updateTicketFlow(id, param);

        // 3、更新 工单模板  2.3 已废弃当前字段, 更新其他字段

        // 4、更新 工单通知
        ticketNotifyConfigService.updateNotifyConfig(id, param);


        // 6、更新TicketConfig 表
        TicketConfig ticketConfig = UpdateConfigParam.paramToEntity(param);
        ticketConfig.setStatusRuleList(param.getDbStatusRuleList());
        String dbId = ticketConfigDao.updateTicketConfig(id, ticketConfig);

        return ServiceResult.success(dbId);
    }


    /**
     * 修改工单配置和工单规则
     *
     * @param entity
     * @param param
     * @return
     * @author liheng
     * @date 2021/8/25 14:24
     */
    private UpdateConfigParam updateTicketRule(TicketConfig entity, UpdateConfigParam param) {
        String ticketRuleId = param.getTicketRuleId();
        //TicketRule.Condition condition = ticketMapper.paramToCondition(Optional.ofNullable(param.getCondition()).orElse(new CreateConfigParam.Condition()));
        TicketRule.Condition condition = ConditionParam.paramToEntity(Optional.ofNullable(param.getCondition()).orElse(new ConditionParam()));
        Integer rultType = param.getRType();
        TicketRule ticketRule = new TicketRule();
        ticketRule.setType(rultType);
        ticketRule.setCondition(condition);
        ticketRule.setId(ticketRuleId);
        ticketRuleService.updateRulesV2(entity.getId(), Collections.singletonList(ticketRule));
        List<TicketRuleParam> statusRuleList = Optional.ofNullable(param.getStatusRuleList()).orElse(new ArrayList<>(10));
        List<JSONObject> statusRuleIdList = new ArrayList<>(10);
        if (CollUtil.isNotEmpty(statusRuleList)) {
            List<TicketRule> ticketRules = ticketRuleMapper.paramsToEntitys(statusRuleList);
            List<String> listServiceResult = ticketRuleService.updateRulesV2(entity.getId(), ticketRules);
            for (int i = 0; i < statusRuleList.size(); i++) {
                TicketRuleParam ticketRuleParam = statusRuleList.get(i);
                if (Objects.nonNull(ticketRuleParam.getId()) && Objects.nonNull(ticketRuleParam.getDeleted()) && ticketRuleParam.getDeleted()) {
                    continue;
                } else {
                    Integer operation = ticketRuleParam.getOperation();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(listServiceResult.get(i), operation);
                    statusRuleIdList.add(jsonObject);
                }
            }
        }
        param.setDbStatusRuleList(statusRuleIdList);
        return param;
    }

    /**
     * 初始化工单基本配置
     *
     * @param param 前端参数
     * @return 初始化的工单基本配置对象
     */
    private TicketConfig initTicketBaseConfig(CreateConfigParam param) {
        TicketConfig ticketConfig = new TicketConfig();
        ticketConfig.setSysId("ticket");
        ticketConfig.setOrgId(param.getOrgId());
        ticketConfig.setUserId(param.getUserId());
        ticketConfig.setTitle(param.getTitle());
        ticketConfig.setSurveyId(param.getSurveyId());
        ticketConfig.setSmtpId(param.getSmtpId());
        ticketConfig.setTicketTemplateId(param.getTicketTemplateId());
        if (StringUtils.isNotBlank(param.getAlertId())) {
            ticketConfig.setAlertId(param.getAlertId());
        }
        return ticketConfigDao.saveTicketConfig(ticketConfig);
    }

    @Override
    public ServiceResult<TicketConfigInfoVO> getTicketConfig(String id) {
        List<TicketConfigInfo> ticketConfigInfos = ticketConfigDao.listTicketConfigInfo(id);
        if (CollectionUtils.isEmpty(ticketConfigInfos)) {
            return ServiceResult.failWithCode(ResourceErrorCodeEnum.NOT_FOUND, "ticketconfig[id=%s] not found' % id");
        }
        TicketConfigInfo ticketConfigInfo = ticketConfigInfos.get(0);
        TicketConfigInfoVO ticketConfigInfoVO = TicketConfigVOConvert.entityToTicketConfigInfoVO(ticketConfigInfo);
        // 使用surveyId请求qdes查询问卷，qdes_get_project(str(ticketconfig.surveyId))
        String surveyId = ticketConfigInfo.getSurveyId();
        QdesDTO qdesProject = ticketBaseQdesGrpcService.getQdesProject(surveyId);
        if (Objects.isNull(qdesProject)) {
            // 如果未查到问卷信息，初始化问卷信息
            // 失败返回 survey_info = {'code': '', 'title': '<问卷消失了>', 'status': QDES_SURVEY_STATUS_DELETE, 'creator': ''}
            qdesProject = new QdesDTO();
            qdesProject.setCode("");
            qdesProject.setTitle("<问卷消失了>");
            qdesProject.setStatus(4);
            qdesProject.setCreator("");
        }

        //  使用surveyInfo中的creator查看userInfo，user_get_user(survey_info["creator"])
        String name = "";
        if (ObjectId.isValid(qdesProject.getCreator())) {
            UserDTO user = ticketBaseUserGrpcService.getUser(qdesProject.getCreator());
            name = Optional.ofNullable(user).map(UserDTO::getName).orElse("");
        }

        ticketConfigInfoVO.setSurveyCode(qdesProject.getCode());
        ticketConfigInfoVO.setSurveyTitle(qdesProject.getTitle());
        ticketConfigInfoVO.setSurveyStatus(qdesProject.getStatus());
        ticketConfigInfoVO.setSurveyCreator(name);

        // 问卷是否有工单
        ticketConfigInfoVO.setSurveyHasTicket(ticketService.checkSurveyHasTicket(surveyId));

        // 处理 工单规则
        ticketConfigInfoVO = ticketRuleService.parseRuleJsonData(ticketConfigInfoVO);

        // 处理 工单通知配置
        ticketConfigInfoVO = ticketNotifyConfigService.parseTicketNotifyConfig(ticketConfigInfoVO);

        // 处理 工单流程和跟进信息
        ticketConfigInfoVO = ticketFlowService.parseTicketFollowConfigData(ticketConfigInfoVO);

        // 处理工单 预警通知配置
        ticketConfigInfoVO.setOnlyNotifyConfig(ticketNotifyConfigService.parseTicketOnlyNotifyConfig(ticketConfigInfoVO));

        // 处理历史数据 详情模板 来源字段展示信息
        List<TemplateDetailFieldVO> templateDetailFields = ticketConfigInfoVO.getTemplateDetailFields();
        ticketConfigInfoVO.setTemplateDetailFields(parseDetailField(templateDetailFields));

        return ServiceResult.success(ticketConfigInfoVO);
    }


    private List<TemplateDetailFieldVO> parseDetailField(List<TemplateDetailFieldVO> templateDetailFields) {
        if (CollectionUtils.isEmpty(templateDetailFields)) {
            return templateDetailFields;
        }

        for (TemplateDetailFieldVO field : templateDetailFields) {
            // 只处理历史数据
            if (!"已设置".equals(field.getOriginText())) {
                continue;
            }

            // 字段id不正确
            if (ObjectUtils.isEmpty(field.getSourceId()) && !ObjectId.isValid(field.getSourceId())) {
                continue;
            }

            ColumnDTO column = ticketBaseSurveyGrpcService.getColumn(field.getSourceId());
            if (Objects.isNull(column)) {
                continue;
            }
            String col = column.getCol();
            // 所选字段为 联系人元数据
            if (!ObjectUtils.isEmpty(col)) {
                field.setOriginText(col);
                continue;
            }

            // 所选字段为 问卷字段
            String customAttrStr = column.getCustomAttr();
            JSONObject jsonObject = JSONObject.parseObject(customAttrStr);
            ColumnDTO.CustomAttr customAttr = JSON.toJavaObject(jsonObject, ColumnDTO.CustomAttr.class);
            // 无 二级标题
            if (ObjectUtils.isEmpty(customAttr.getRtitle())) {
                // 级联
                if (!ObjectUtils.isEmpty(customAttr.getOption())) {
                    customAttr.setRtitle(customAttr.getOption());
                } else {
                    // 其他问题
                    customAttr.setRtitle("问题");
                }
            }
            // 选项 - 一级标题 + 二级标题
            String originText = String.format("%s-%s+%s", customAttr.getCid(), customAttr.getTitle(), customAttr.getRtitle());
            // 三级标题不为空
            if (!Constants.BLANK.equals(customAttr.getOtitle())) {
                originText += "+" + customAttr.getOtitle();
            }
            field.setOriginText(originText);
        }

        return templateDetailFields;
    }

}
